﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Omu.Awesome.Core;
using XPressify.Core;
using XPressify.Data;
using XPressify.Data.Helpers;
using XPressify.Helpers;
using XPressify.Models;
using NotificationType = XPressify.Models.NotificationType;

namespace XPressify.Controllers
{
    public class ThreadController : BaseController
    {
        //
        // GET: /Thread/
        [Authorize]
        public ActionResult ThreadList(int? page)
        {

            var user = CurrentUser;
            var allThreads =
                Repository.AsQueryable<Thread>().Where(
                    thread => thread.ThreadParticipants.Any(part => part.BaseSubject.Id == user.Id && part.IsDeleted == false));
            var threadPageable = allThreads.GetPageable(page ?? 1, 5, (g => g.Messages.OrderByDescending(m => m.Created).First().Created ));
            var model = new List<ThreadListModel>();

            foreach (var allThread in threadPageable.Page)
            {

                var lastMessage = allThread.Messages.OrderByDescending(m => m.Created).First(); // last message sent
                string lastMessageBody = lastMessage.Body;
                var lastMessageBodyLenght = lastMessageBody.Length > 60 ? 60 : lastMessageBody.Length;
                if(lastMessageBody.Length > 60)
                {
                    lastMessageBody = lastMessageBody.Substring(0, lastMessageBodyLenght) + "...";
                }
                else
                {
                    lastMessageBody = lastMessageBody.Substring(0, lastMessageBodyLenght);
                }
                var participatns = allThread.ThreadParticipants.Where(th => th.BaseSubject.Id != user.Id);
                var creatorOfLastMessage = participatns.First().BaseSubject; // participant which is not current user
                var lastMessageProfilePicturePath = Repository.GetProfilePicturePath(creatorOfLastMessage.Id); // profile of participant which is not current user

                var threadParticipant =
                    Repository.AsQueryable<ThreadParticipant>().SingleOrDefault(
                        th => th.Thread.Id == allThread.Id && th.BaseSubject.Id == user.Id);

                ThreadListModel oneThread = new ThreadListModel
                                            {
                                                Id = allThread.Id,
                                                Subject = allThread.Subject,
                                                LastMessageUser = (User)creatorOfLastMessage, // participant which is not current user
                                                ProfilePicturePath = lastMessageProfilePicturePath,
                                                LastMessageCreated = lastMessage.Created,
                                                LastMessageBody = lastMessageBody,
                                                IsRead = threadParticipant.IsRead
                                            };
                model.Add(oneThread);
            }
            var threadModelPageable = new Pageable<ThreadListModel> { Page = model, PageCount = threadPageable.PageCount, PageIndex = threadPageable.PageIndex };
            return View("ThreadList", threadModelPageable);
        }


        //
        // GET: /Thread/Create
        [Authorize]
        public ActionResult ThreadCreate()
        {
            var user = CurrentUser;
            var allFriends = Repository.GetFriendsOf(user.Id);
            var friendsLookupList = new List<FriendsLookupModels>();
            foreach (var friend in allFriends)
            {
                var newMember = new FriendsLookupModels()
                {
                    FirstName = friend.FirstName,
                    Fullname = friend.FullName,
                    LastName = friend.LastName,
                    Id = friend.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                    Selected = false
                };
                friendsLookupList.Add(newMember);
            }
            var json = JsonHelper.Serialize(friendsLookupList);
            Session["allFriends"] = json;
            
            var model = new ThreadCreateModel()
                            {
                                CurrentUserId = CurrentUser.Id
                            };
            return View(model);
        } 

        //
        // POST: /Thread/Create
        [Authorize]
        [HttpPost]
        public ActionResult ThreadCreate(ThreadCreateModel model)
        {
            if(ModelState.IsValid)
            {
                try
                {
                    if(model.UsersSelected == null)
                    {
                        return View(model);
                    }
                    var user = CurrentUser;
                    var thread = new Thread
                    {
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Thread,
                        Created = DateTime.Now,
                        Subject = model.Subject,
                        BaseSubject = user,
                        Read = false
                    };

                    var message = new Message
                    {
                        BaseSubject = user,
                        Body = model.Message,
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Message,
                        Thread = thread
                    };
                    Repository.AddObject(thread);

                    var threadParticipant = new ThreadParticipant
                                                {
                                                    BaseSubject = user,
                                                    Id = Guid.NewGuid(),
                                                    IsDeleted = false,
                                                    IsRead = true,
                                                    Thread = thread
                                                };
                    Repository.AddObject(threadParticipant);
                  
                    Repository.AddObject(message);
                    Repository.SaveChanges();

                    var selectedUsers = Repository.AsQueryable<User>().Where(u => model.UsersSelected.Contains(u.Id));

                    foreach (var participant in selectedUsers)
                    {
                        threadParticipant = new ThreadParticipant
                        {
                            BaseSubject = participant,
                            Id = Guid.NewGuid(),
                            IsDeleted = false,
                            IsRead = false,
                            NewMessage = true, // they got new message
                            Thread = thread
                        };

                        Repository.AddObject(threadParticipant);
                        var mailModel = new ThreadSendEmailModel
                        {
                            Created = thread.Created,
                            Sender = thread.BaseSubject.FullName,
                            MessageBody = message.Body,
                            Subject = thread.Subject,
                            ThreadId = thread.Id,
                            Receiver = participant
                        };
                        SendEmail(mailModel);
                    }
                    Repository.SaveChanges();

                    return Json(model);
                }
                catch
                {
                    return View(model);
                }
            }
            return View(model);
        }
        

        [Authorize]
        [HttpPost]
        public ActionResult ThreadDelete(ThreadDeleteModel model)
        {
            try
            {
                var thread = Repository.AsQueryable<Thread>().SingleOrDefault(th => th.Id == model.Id);
                var user = CurrentUser;
                var deleteThread = Repository.AsQueryable<ThreadParticipant>().SingleOrDefault(x => x.Thread.Id == model.Id && x.BaseSubject.Id == user.Id); // set as deleted
                deleteThread.IsDeleted = true;
                var threadParticipants = thread.ThreadParticipants;
                bool allDeleted = true;
                foreach (var threadParticipant in threadParticipants) // check if all participants set this thread as deleted. if so then we delete the thread
                {
                    if (threadParticipant.IsDeleted == false)
                    {
                        allDeleted = false;
                        break;
                    }
                }
                if (allDeleted)
                {
                    var participants =
                        Repository.AsQueryable<ThreadParticipant>().Where(par => par.ThreadId == thread.Id).ToArray();
                    //delete all participants
                    foreach (var participant in participants)
                    {
                        Repository.DeleteObject(participant);
                    }

                    var messages = Repository.AsQueryable<Message>().Where(mes => mes.Thread.Id == thread.Id).ToArray();

                    //delete all messages
                    foreach (var message in messages)
                    {
                        message.BaseSubject = null;
                        Repository.DeleteObject(message);
                    }

                    //delete the thread
                    Repository.DeleteObject(thread);
                    
                }
                Repository.SaveChanges();
                return PartialView("EmptyView");
            }
            catch
            {
                return View(model);
            }
        }


        public ActionResult MakeAsUnread(Guid id)
        {
            var thread = Repository.AsQueryable<Thread>().SingleOrDefault(th => th.Id == id);
            var user = CurrentUser;
            var threadParticipant =
                Repository.AsQueryable<ThreadParticipant>().SingleOrDefault(
                    th => th.Thread.Id == thread.Id && th.BaseSubject.Id == user.Id);
            threadParticipant.IsRead = false;
            Repository.SaveChanges();
            return RedirectToAction("ThreadList", "Thread", new { });
        }


        #region Email Sending

        [Authorize]
        public bool SendEmail(ThreadSendEmailModel model)
        {
            var user = CurrentUser;
            var viewData = new
            {
                XSettings.SiteName,
                YourName = user.FullName,
                model.Sender, 
                model.Created, 
                model.MessageBody, 
                model.Subject,
                ReplyUrl =
                    new Uri(HttpContext.Request.Url, Url.Action("CreateMessage", "Message", new { id = model.ThreadId })).
                        ToString(),
                YourProfileUrl =
                               new Uri(HttpContext.Request.Url,
                                       Url.Action("ProfileView", "Profile", new { id = user.Id })).ToString(),
                XSettings.SiteUrl
            };

            var viewDictionary = viewData.ToViewDataDictionary();

            // send an activation email
            return SendTemplatedEmail(new List<string> { model.Receiver.Email }, String.Format("{0} site: New message", XSettings.SiteName),
                                                   "~/Views/Email/MessageEmailSend.cshtml", viewDictionary);
        }

        #endregion


    }
}
